package minesweep.entity;

import org.json.JSONArray;

import java.util.ArrayList;
import java.util.Collections;

import static minesweep.constant.ProtocolConstant.GIRD_NOT_OPENED;
/**
 * Created by fuatnow on 17/2/9.
 */


class MarkInfo
{
    public int row;
    public int col;
    public int usrID;
    public boolean maredMine;
}

class Coord
{
    public int row;
    public  int col;
    public Coord(int row,int col)
    {
        this.row = row;
        this.col = col;
    }

    public boolean isEqual(Coord other)
    {
        return (row == other.row) && (col == other.col);
    }
}

public class GameBoard
{
    private int minesNum;
    private ArrayList<ArrayList<Integer>> boardArray;
    private ArrayList<ArrayList<Boolean>> boardOpendArray;
    private int max_row = 10;
    private int max_col = 9;
    public  GameBoard()
    {
        this.minesNum = (int)(Math.random()*15)+4;
        this.boardArray = generBoardData(this.minesNum);
        this.boardOpendArray = new ArrayList<ArrayList<Boolean>>();
        for(int i=0;i<this.boardArray.size();i++)
        {
            ArrayList<Integer> rowArray = this.boardArray.get(i);
            ArrayList<Boolean> rowArr = new ArrayList<Boolean>();
            for(int j=0;j<rowArray.size();j++)
            {
                rowArr.add(false);
            }
            this.boardOpendArray.add(rowArr);
        }
    }

//    public GameBoard(int minesNum) {
//        this.minesNum = minesNum;
//    }

    private ArrayList<ArrayList<Integer>> generBoardData(int minesNum)
    {
        int maxBoardNum = max_row*max_col - max_row/2;
        ArrayList<Integer> numLis = new ArrayList<Integer>();
        for(int i=0;i<maxBoardNum;i++)
        {
            numLis.add(i<minesNum ? -1 : 0);
        }
        Collections.shuffle(numLis);


        ArrayList<ArrayList<Integer>> data = new ArrayList<ArrayList<Integer>>();
        for(int i=0,startIndex = 0;i<max_row;i++)
        {
            int endLen=  (i %2 == 0 ? max_col :max_col -1);
            ArrayList<Integer> subList =  new ArrayList<Integer>();
            for(int j=startIndex;j<startIndex+endLen;j++)
            {
                subList.add(numLis.get(j));
            }
            data.add(subList);
            startIndex+=endLen;
        }

        for(int i=0;i<data.size();i++)
        {
            ArrayList<Integer> lis = data.get(i);
            for(int j=0;j<lis.size();j++)
            {
                if(lis.get(j) == -1) continue;
                ArrayList<Coord> legalLis = this.getLegaldjacentCoord(i,j);
                for(int k=0;k<legalLis.size();k++)
                {
                    Coord coord = legalLis.get(k) ;
                    int row = coord.row;
                    int col = coord.col;
                    if(data.get(row).get(col) < 0)
                    {
                        int curNum = data.get(i).get(j);
                        int newNum = (curNum < 0 ? 1 : curNum+1);
                        ArrayList<Integer> rowLis = data.get(i);
                        rowLis.set(j,newNum);
                    }
                }
            }
        }

        return data;
    }

    boolean isMine(int row ,int col)
    {
        if(row<0 || row > max_row-1 || col < 0 || col > max_col -1 ) return  false;
        //-1是雷
        return this.boardArray.get(row).get(col) == -1;
    }

    //获取合法相邻坐标
    private ArrayList<Coord> getLegaldjacentCoord(int row,int col)
    {
        ArrayList<Coord> lis = new  ArrayList<Coord>();
        Coord tL = new Coord(row-1,row % 2 ==0 ? col-1 :col);
        Coord tR =  new Coord(row-1,row % 2 ==0 ? col :col+1);

        Coord l =  new Coord(row,col-1);
        Coord r =new Coord(row,col+1);

        Coord bL = new Coord(row+1,tL.col);
        Coord bR = new Coord(row+1,tR.col);

        int curColLen = (row % 2 == 0 ? max_col : max_col-1);
        int topLen = max_col;
        int bottomLen = max_col;
        if(row % 2 == 0)
        {
            curColLen = max_col;
            topLen = max_col-1;
            bottomLen = max_col-1;
        }
        if(tL.row >= 0)
        {
            if(tL.col >= 0) lis.add(tL);
            if(tR.col < topLen) lis.add(tR);
        }

        if(l.row >= 0)
        {
            if(l.col >= 0) lis.add(l);
            if(r.col < curColLen) lis.add(r);
        }

        if(bL.row < max_row)
        {
            if(bL.col >= 0) lis.add(bL);
            if(bR.col < bottomLen) lis.add(bR);
        }
        return lis;
    }

    private boolean contains(ArrayList<Coord> coordArr, Coord coord)
    {
        for(int i=0;i<coordArr.size();i++)
        {
            Coord coordTmp = coordArr.get(i);
            boolean isEqul = coordTmp.isEqual(coord);
            if(isEqul)
            {
                return true;
            }
        }
        return false;
    }

    public void touchGird(int coodrX,int coordY)
    {
        if(this.boardOpendArray.get(coodrX).get(coordY) == true) return;
        ArrayList<Coord> newShowArr = new ArrayList<Coord>();
        this.isTouchInMine(coodrX,coordY,newShowArr);
        for(int i=0;i<newShowArr.size();i++)
        {
            Coord tmp = newShowArr.get(i);
            ArrayList<Boolean> boolRowArr = this.boardOpendArray.get(tmp.row);
            boolRowArr.set(tmp.col,true);
        }
    }

    //坐标xy 二维数组 返回新增的显示列表
    boolean isTouchInMine(int coordX,int coordY,ArrayList<Coord>  newShowLis)
    {
        int val = this.boardArray.get(coordX).get(coordY);
        Coord coord = new Coord(coordX,coordY);
        newShowLis.add(coord);
        if(val == -1)
        {
            return true;
        }
        else
        {
            if(val == 0)
            {
                ArrayList<Coord>  lis = this.getLegaldjacentCoord(coordX,coordY);
                for(int i=0;i<lis.size();i++)
                {
                    Coord coordTmp = lis.get(i);
                    if(this.contains(newShowLis,coordTmp) == false)
                    {
                        int row = coordTmp.row;
                        int col = coordTmp.col;
                        this.isTouchInMine(row,col,newShowLis);
                    }
                }
            }
            return false;
        }
    }


    public JSONArray getBoardJsonArry()
    {
        JSONArray bArr = new JSONArray();
        for(int i=0;i<this.boardOpendArray.size();i++)
        {
            ArrayList<Boolean> rowArr = this.boardOpendArray.get(i);
            JSONArray jArr = new JSONArray();
            for(int j=0;j<rowArr.size();j++)
            {
                boolean isOpend = rowArr.get(j);
                int girdNum = this.boardArray.get(i).get(j);
                if(isOpend == false)
                {
                    girdNum = GIRD_NOT_OPENED;//表示这个位置还没有被揭开
                }
                jArr.put(girdNum);
            }
            bArr.put(jArr);
        }
        return bArr;
    }

    public int getRemainMinesNum()
    {
        int rMinesNum  = 0;
        for(int i=0;i<this.boardArray.size();i++)
        {
            ArrayList<Integer> rowArray = this.boardArray.get(i);
            for(int j=0;j<rowArray.size();j++)
            {
                    if(boardOpendArray.get(i).get(j) == false && boardArray.get(i).get(j) == -1)
                    {
                        rMinesNum++;
                    }
            }
        }
        return rMinesNum;
    }

    public void setMinesNum(int minesNum) {
        this.minesNum = minesNum;
    }
}
